using Microsoft.Extensions.DependencyInjection;
using System.Collections.Concurrent;
using TrackSystem.Contracts;
using TrackSystem.IO.Alarm;
using TrackSystem.IO.Logics;
using TrackSystem.IO.Loops;
using TrackSystem.IO.Models;
using TrackSystem.IO.Sensors;
using TrackSystem.IO.Utils;

namespace TrackSystem.IO.Equip;

/// <summary>
/// 装备平台工厂类
/// </summary>
public class EquipFactory
{
    /// <summary>
    /// 实例句柄
    /// </summary>
    public static readonly EquipFactory Instance;

    private ConcurrentDictionary<int, EquipItem>? Items { get; set; }

    /// <summary>
    /// 是否载入设备
    /// </summary>
    private bool bLoad = false;

    /// <summary>
    /// 构造函数
    /// </summary>
    static EquipFactory()
    {
        Instance = new EquipFactory();
        Instance.Create();
    }

    /// <summary>
    /// 初始化函数
    /// </summary>
    private void Create()
    {
        Items = new ConcurrentDictionary<int, EquipItem>();
    }

    /// <summary>
    /// 载入函数
    /// </summary>
    /// <param name="wrapper"></param>
    /// <returns></returns>
    public async Task<ResultMsg> Load(IRepositoryWrapper wrapper, IServiceScopeFactory serviceScope)
    {
        UnLoad();

        try
        {
            var lstEquipEntity = await wrapper.Equip.GetAllListAsync();
            foreach (var item in lstEquipEntity)
            {
                EquipItem equip = new() { 
                    Name = item.Name,
                    Description = item.Description,
                    Parts = new()
                };

                Items?.TryAdd(item.Id, equip);
                // 找到装备对象的传感器、逻辑变量、控制回路、把它载入的装备中
                foreach (var sensor in SensorFactory.Instance.Items.Values)
                {
                    if (Items is not null && Items.TryGetValue(sensor.EquipId, out var equipItem))
                    {
                        equipItem.TryAddSensor(sensor);
                    }
                }

                foreach (var logic in LogicFactory.Instance.Items.Values)
                {
                    if (Items is not null && Items.TryGetValue(logic.EquipId, out var equipItem))
                    {
                        equipItem.TryAddLogic(logic);
                    }
                }

                foreach (var loop in LoopFactory.Instance.Items.Values)
                {
                    if (Items is not null && Items.TryGetValue(loop.EquipId, out var equipItem))
                    {
                        equipItem.TryAddLoop(loop);
                    }
                }
            }

            await AlarmFactory.Instance.Load(wrapper, serviceScope);

            return ResultMsg.Succ("载入设备成功");
        }
        catch (Exception e)
        {
            return ResultMsg.Fail($"载入设备出错，{e.Message}");
        }
    }

    /// <summary>
    /// 卸载
    /// </summary>
    public void UnLoad()
    {
        if (Items?.Values == null) return;
        foreach (var item in Items.Values)
        {
            item.Parts?.Clear();
        }

        Items.Clear();

        AlarmFactory.Instance.Dispose();
    }

    /// <summary>
    /// 查询成员
    /// </summary>
    /// <param name="id"></param>
    /// <param name="item"></param>
    /// <returns></returns>
    public bool TryGetValue(int id, out EquipItem? item)
    {
        if (Items is not null)
            return Items.TryGetValue(id, out item);
        item = null;
        return false;
    }

    public bool TryAdd(int id, EquipItem item)
    {
        if (Items is null)
        {
            Items = new();
        }

        return Items.TryAdd(id, item);
    }

    /// <summary>
    /// 获取全部成员
    /// </summary>
    /// <returns></returns>
    public IEnumerable<EquipItem> GetAll()
    {
        Items ??= new();
        return [.. Items.Values];
    }

    /// <summary>
    /// 更新状态
    /// </summary>
    public void Update()
    {
        if (Items is null || Items.IsEmpty) return;

        foreach(var item in Items.Values)
        {
            if (item.Parts is null)
                continue;

            foreach (var part in item.Parts.Values)
            {
                switch (part.Catogery)
                {
                    case EquipPartCatogery.SENSOR:
                    {
                        if (!SensorFactory.Instance.Items.TryGetValue(part.Name ??= "", out var sensor)) continue;
                        part.Enabled = sensor.Enabled;
                        part.Status = sensor.Succ_R > 0 || sensor.Succ_W > 0;
                        break;
                    }
                    case EquipPartCatogery.LOGIC:
                    {
                        if (!LogicFactory.Instance.Items.TryGetValue(part.Name ??= "", out var logic)) continue;
                        part.Enabled = logic.Enabled;
                        part.Status = (logic.condValue is null)?false : logic.condValue.bVal;
                        break;
                    }
                    case EquipPartCatogery.LOOP:
                    {
                        if (!LoopFactory.Instance.Items.TryGetValue(part.Name ??= "", out var loop)) continue;
                        part.Enabled = loop.Enabled;
                        part.Status = !loop.Manual;
                        break;
                    }
                }
            }
        }
    }

}